/*
 * connection_listener.cpp
 *
 *  Created on: 2009-1-7
 *      Author: fanliangliang
 */

#include "connection_listener.h"
#include "common_struct.h"
#include "file_receiver.h"
#include "protocol.h"
#include "common_packet.h"
#include "application.h"
#include <memory> // for auto_ptr

using namespace std;
using namespace toxic;

ConnectionListener::ConnectionListener(FileReceiver* receiver, Application* application)
:application_(application)
,receiver_(receiver)
,isRunning_(true) {
}

ConnectionListener::~ConnectionListener() {

}

static DataTable* statusToDataTable(int16_t status) {
	DataTable* table = new DataTable();
	table->addColumn("isReceiving");
	table->addColumn("isSending");
	table->addColumn("isUncompressing");
	table->addColumn("isIdle");

	bool isReceiving = (status & DU::STATUS_RECEIVING) != 0;
	bool isSending = (status & DU::STATUS_SENDING) != 0;
	bool isUncompressing = (status & DU::STATUS_UNCOMPRESSING) != 0;
	bool isIdle = (status & DU::STATUS_ALL_IDLE) != 0;

	DataRow* row = new DataRow();
	row->push_back(isReceiving);
	row->push_back(isSending);
	row->push_back(isUncompressing);
	row->push_back(isIdle);

	table->push_back(row);
	return table;
}

void ConnectionListener::run() {
	server_.listen(8988);
	while (isRunning_) {
		try {
			// wait for incoming connection
			auto_ptr<TcpSocket> socket(server_.accept());

			xdebug << "accept new sender {" << socket->peerAddress() << "}";

			// query receiver status
			int16_t status = application_->status();

			auto_ptr<DataTable> table(statusToDataTable(status));
			xtrace << "start sending ReceiverStatusPacket\n" << *table;

			ReceiverStatusPacket rsp;
			rsp.setStatus(status);
			rsp.sendVia(socket.get());

			xtrace << "finish sending ReceiverStatusPacket";

			if (rsp.isReceiveReady()) {
				xdebug << "receiver is ready";
				// notify receiver
				receiver_->push(socket.release());
			}
			else {
				xdebug << "receiver is not ready, connection will be closed";
			}
			// we are busy, auto close connection
		}
		catch (const exception& e) {
			xerror << e.what();
		}
		catch (...) {
			xerror << "oops, caught an unexpected exception";
		}
	}
}

void ConnectionListener::stop() {
	isRunning_ = false;
	server_.close();
}
